from datetime import datetime, timedelta
import time

class MetricVariables:

    collection_mins = None
    last_collected = None
    next_collection_time = None
    shadow_time = None
    site_collection_time = None

    def __init__(self, metric_site, collection_time=None):
        if collection_time is None:
            collection_time = datetime.now()

        self.site_collection_time = self.nominal_check_time(collection_time, metric_site.check_mins)

        self.collection_mins = None
        self.last_collected = None
        self.next_collection_time = None
        self.shadow_time = None
        
    def fit_set(self, metric_set):
        self.collection_mins = metric_set.collection_mins
        self.last_collected = metric_set.last_collected

        self.collection_time = self.nominal_check_time(self.site_collection_time, self.collection_mins)
        self.next_collection_time, self.shadow_time = self.next_check(metric_set)

    def nominal_check_time(self, collection_time, check_mins):
        check_timedelta = timedelta(seconds=check_mins*60)
    
        # Round time given to nearest whole period based on site_check_mins.
        # So if collection_time is 16:03:10, and check_mins=60, just set
        # nominal_check_time to 16:00:00.
    
        timestamp = time.mktime(collection_time.timetuple())
        roughedge = timedelta(seconds=(timestamp % (check_mins*60)), microseconds=collection_time.microsecond)
    
        # If more than half way through check_mins time period, bump up to next whole-number time instead
        if roughedge > check_timedelta / 2:
            roughedge -= check_timedelta 
    
        return collection_time - roughedge

    def next_check(self, metric_set):

        # Calculate shadow time
        shadow_time = self.collection_time - timedelta(minutes=metric_set.shadow_mins)

        # When should we check again
        if self.last_collected is None:
            next_check_time = self.collection_time
        else:
            next_check_time = self.last_collected + timedelta(seconds=metric_set.collection_mins*60)

        return (next_check_time, shadow_time)
